Fix keyword-merge 500 on legacy sort_value column (#1352)#1362
Conversation
The keyword-merge action 500'd on -test/prod with "null value in column sort_value violates not-null constraint". The deployed website_*_keywords through tables carry a leftover NOT-NULL sort_value column (keywords used to be a SortedManyToManyField), so obj.keywords.add(target) — which INSERTs a fresh through row — fails the constraint. settings_test builds the schema from the current plain-M2M models, so the column isn't present locally and the original tests couldn't catch it. Fix: merge at the through-table level by repointing each existing (object, source) row to (object, target) — an UPDATE that preserves the row's sort_value — instead of inserting a new row. If the object already has the target (including when it's tagged with two sources at once), the source row is deleted so no duplicate (object, keyword) pair is created. Adds a regression test that reproduces the deployed drift by adding a NOT-NULL sort_value column to the through table before merging, plus a two-sources-on- one-object dedup test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Root cause verified against the prod dump (2026-06-14)Confirmed this is a legacy
So: the field was once The repoint approach in this PR is correct for both the nullable (prod) and NOT NULL (-test) variants. Related latent bug (separate follow-up)On |
|
The deeper cleanup (dropping the vestigial |
Keyword taxonomy cleanup (#1352): "Merge selected keywords" admin action, "Duplicate keywords" Data Health check with deep links to the merge changelist, and whitespace normalization on Keyword.save(). Merge operates at the M2M through-table level for compatibility with the legacy sort_value column on website_publication_keywords (#1362). Admin hygiene (#1346): Photo changelist no longer 500s on a missing image file and surfaces the owning project. Plus SEO on-page fixes (duplicate <title>, /None sponsor links, YouTube embed). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Follow-up bugfix to #1361. The "Merge selected keywords" action 500'd on
-testwith:Root cause
The deployed
website_*_keywordsthrough tables carry a leftover NOT-NULLsort_valuecolumn —keywordsused to be aSortedManyToManyField(likeauthors/project_umbrellas). Soobj.keywords.add(target), which INSERTs a fresh through row, fails the constraint.settings_testbuilds the schema from the current plain-ManyToManyFieldmodels, so the column isn't present locally — which is exactly why the original tests passed but prod/-test failed.Fix
Merge at the through-table level: repoint each existing
(object, source)row to(object, target)(an UPDATE that preservessort_value) instead of inserting a new row. If the object already carries the target — including when it's tagged with two source keywords at once — the source row is deleted so no duplicate(object, keyword)pair is created.Tests
sort_valuecolumn to the through table before merging (SET CONSTRAINTS ALL IMMEDIATEto clear the deferred FK triggers first), and asserts the merge succeeds.test_keyword_merge+test_data_health+test_admin_changelist(50 tests).🤖 Generated with Claude Code